#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include <iostream>
using std::cout;
using std::endl;
using std::string;

#include <workflow/WFFacilities.h>
#include <workflow/WFHttpServer.h>
#include <workflow/HttpUtil.h>
#include <workflow/HttpMessage.h>
#include <workflow/RedisMessage.h>


//通过构造函数初始化计数器的值 
static WFFacilities::WaitGroup waitGroup(1);

struct SeriesContext
{
    protocol::HttpResponse * resp;
    string password;
};

void sighandler(int num)
{
    printf("sig %d is coming\n", num);
    //将计数器的值减1
    waitGroup.done();
}

void httpCallback(WFHttpTask * )
{
    printf("httpCallback is running.\n");
}

void redisCallback(WFRedisTask * redistask)
{
    printf("redisCallback is running.\n");
    //0. 对任务的状态进行检测
    int state = redistask->get_state();
    printf("state: %d\n", state);
    int error = redistask->get_error();
    if(state != WFT_STATE_SUCCESS) {
        printf("error ocurrs: %s\n", WFGlobal::get_error_string(state, error));
        return;
    }
    protocol::RedisValue result;
    redistask->get_resp()->get_result(result);
    if(result.is_string()) {
        string password = result.string_value();
        cout << "redis resp password:" << password << endl;
        //获取共享数据，进行验证
        SeriesContext * data = (SeriesContext*)series_of(redistask)->get_context();
        if(password == data->password) {
            //登录成功
            data->resp->append_output_body("Login SUCESS");
        } else {
            //登录失败
            data->resp->append_output_body("Login Failed");
        }
    }
}

void process(WFHttpTask * serverTask)
{
    printf("\n\nprocess is running.\n");
    //0. 设置任务的回调函数
    serverTask->set_callback(httpCallback);
    //1. 对任务的状态进行检测
    int state = serverTask->get_state();
    printf("state: %d\n", state);
    int error = serverTask->get_error();
    if(state != WFT_STATE_TOREPLY) {
        printf("error ocurrs: %s\n", WFGlobal::get_error_string(state, error));
        return;
    }
    //2. 解析请求
    auto req = serverTask->get_req();
    auto resp = serverTask->get_resp();
    string uri = req->get_request_uri();
    string method = req->get_method();
    cout << method << " " << uri << endl;
    if(method == "GET" && uri == "/login") {
    //  http://192.168.30.128:8888/login
        //读取本地的postform.html文件
        int fd = open("postform.html", O_RDONLY);
        if(fd < 0) {
            perror("open");
            resp->append_output_body("404 not found");
            return;
        }
        char buff[1024] = {0};
        int ret = read(fd, buff, sizeof(buff));
        printf("read ret: %d\n", ret);
        //生成响应信息
        resp->add_header_pair("Content-Type", "text/html");
        resp->append_output_body(buff, ret);
        close(fd);
    }else if(method == "POST" && uri == "/login") {
        cout << "uri: "  << uri << endl;  
        const void * body = nullptr;
        size_t sz = 0;
        req->get_parsed_body(&body, &sz);
        string strbody((const char *)body, sz);
        // username=liubei&password=1234
        cout << "strbody: " << strbody << endl;
        // username=liubei
        string usernameKV = strbody.substr(0, strbody.find("&"));
        // password=123
        string passwordKV = strbody.substr(strbody.find("&") + 1);
        string username = usernameKV.substr(usernameKV.find("=") + 1);
        string password = passwordKV.substr(passwordKV.find("=") + 1);
        cout << "username: " << username << endl;
        cout << "password: " << password << endl;
        //2.1 设置共享数据
        SeriesContext * data = new SeriesContext;
        data->resp = serverTask->get_resp();
        data->password = password;
        series_of(serverTask)->set_context(data);

        //3. 进行登录的验证
        string redisURL("redis://127.0.0.1:6379");
        auto redisTask = WFTaskFactory::create_redis_task(redisURL, 1, redisCallback);
        //3.1 设置任务的属性
        string command("GET");
        std::vector<string> params{username};
        redisTask->get_req()->set_request(command, params);
        //3.2 将Redis任务添加到序列之中
        series_of(serverTask)->push_back(redisTask);
    }    
}

void test0()
{
    signal(SIGINT, sighandler);

    WFHttpServer httpServer(process);
    
    if(httpServer.start(8888) == 0) {
        waitGroup.wait();
        httpServer.stop();
    }

}


int main()
{
    test0();
    printf("exit main\n");
    return 0;
}

